// arrayBuffer转base64
const abToBase64 = (bytes) => {
  let binary = ''
  const len = bytes.byteLength
  for (let i = 0; i < len; i++) {
    binary += String.fromCharCode(bytes[i])
  }
  return window.btoa(binary)
}

// uint8Array合并
const concatenate = (ResultConstructor, ...arrays) => {
  let totalLength = 0
  for (const arr of arrays) {
    if (arr.byteLength) {
      totalLength += arr.byteLength
    } else if (arr.length) {
      totalLength += arr.length
    }
  }
  const result = new ResultConstructor(totalLength)
  let offset = 0
  for (const arr of arrays) {
    result.set(arr, offset)
    offset += arr.length
  }
  return result
}

// blob数据转blobUrl
const blobToUrl = (blobData) => {
  return window.URL.createObjectURL(blobData)
}

// 字符串转uint8数组
const strToUint8 = (str, Constructor) => {
  // const bufView = new Constructor(str.length)
  // for (let i = 0; i < str.length; i++) {
  //   bufView[i] = str.charCodeAt(i)
  // }
  // return bufView
  const bytes = []
  const len = str.length
  let c
  for (let i = 0; i < len; i++) {
    c = str.charCodeAt(i)
    if (c >= 0x010000 && c <= 0x10FFFF) {
      bytes.push(((c >> 18) & 0x07) | 0xF0)
      bytes.push(((c >> 12) & 0x3F) | 0x80)
      bytes.push(((c >> 6) & 0x3F) | 0x80)
      bytes.push((c & 0x3F) | 0x80)
    } else if (c >= 0x000800 && c <= 0x00FFFF) {
      bytes.push(((c >> 12) & 0x0F) | 0xE0)
      bytes.push(((c >> 6) & 0x3F) | 0x80)
      bytes.push((c & 0x3F) | 0x80)
    } else if (c >= 0x000080 && c <= 0x0007FF) {
      bytes.push(((c >> 6) & 0x1F) | 0xC0)
      bytes.push((c & 0x3F) | 0x80)
    } else {
      bytes.push(c & 0xFF)
    }
  }
  return new Constructor(bytes)
}

// 数字转uint8数组
const numToUint8 = (num, Constructor) => {
  const hex = '0x' + num.toString(16)
  const needByteArray = new Constructor([hex])
  const uint8array = new Uint8Array(needByteArray.buffer)
  return uint8array.reverse()
}

// uint8数组截取
const uint8Intercept = (uint8array, firstIndex, length) => {
  return new Uint8Array(uint8array, firstIndex, length)
}

// uint8数组转string
const uint8ToStr = (uint8array) => {
  // let dataString = ''
  // for (let i = 0; i < uint8array.length; i++) {
  //   dataString += String.fromCharCode(uint8array[i])
  // }
  // return dataString
  let str = ''
  const arr = uint8array
  for (let i = 0; i < arr.length; i++) {
    const one = arr[i].toString(2)
    const v = one.match(/^1+?(?=0)/)
    if (v && one.length === 8) {
      const bytesLength = v[0].length
      let store = arr[i].toString(2).slice(7 - bytesLength)
      for (let st = 1; st < bytesLength; st++) {
        store += arr[st + i].toString(2).slice(2)
      }
      str += String.fromCharCode(parseInt(store, 2))
      i += bytesLength - 1
    } else {
      str += String.fromCharCode(arr[i])
    }
  }
  return str
}

// uint8数组转数字
const uint8ToNum = (uint8array, type) => {
  const view = new DataView(new ArrayBuffer(uint8array.length))
  for (let i = 0; i < uint8array.length; i++) {
    view.setUint8(i, uint8array[i])
  }

  if (!view.getBigUint64) {
    view.getBigUint64 = () => {
      let num = 0
      for (let i = uint8array.length - 1; i >= 0; i--) {
        if (uint8array[i]) {
          num += i * Math.pow(256, uint8array.length - i - 1)
        }
      }
      return num
    }
  }
  switch (type) {
    case 8: {
      return view.getUint8()
    }
    case 16: {
      return view.getUint16()
    }
    case 32: {
      return view.getUint32()
    }
    case 64: {
      return view.getBigUint64()
    }
  }
}

export default {
  abToBase64,
  concatenate,
  blobToUrl,
  strToUint8,
  numToUint8,
  uint8Intercept,
  uint8ToStr,
  uint8ToNum
}
